package cc.decat.escript.object;

import java.util.Objects;

public class ESIntegerObject extends ESObject {

    public static ESIntegerObject fromValue(Long val) {
        return new ESIntegerObject(val);
    }

    private long value;

    private ESIntegerObject(long value) {
        super(ESIntegerType.getInstance());
        this.value = value;
    }

    public long getValue() {
        return value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ESIntegerObject that = (ESIntegerObject) o;
        return value == that.value;
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
}

class ESIntegerType extends ESType {

    private static final ESIntegerType instance = new ESIntegerType();

    public ESIntegerType() {
        super("Integer");
    }

    public static ESIntegerType getInstance() {
        return instance;
    }

    @Override
    public ESObject str(ESObject x) {
        return ESStringObject.fromValue(String.valueOf(((ESIntegerObject)x).getValue()));
    }

    @Override
    public ESObject add(ESObject lhs, ESObject rhs) {
        return ESIntegerObject.fromValue(((ESIntegerObject)lhs).getValue() + ((ESIntegerObject)rhs).getValue());
    }

    @Override
    public ESObject sub(ESObject lhs, ESObject rhs) {
        return ESIntegerObject.fromValue(((ESIntegerObject)lhs).getValue() - ((ESIntegerObject)rhs).getValue());
    }

    @Override
    public ESObject mul(ESObject lhs, ESObject rhs) {
        return ESIntegerObject.fromValue(((ESIntegerObject)lhs).getValue() * ((ESIntegerObject)rhs).getValue());
    }

    @Override
    public ESObject div(ESObject lhs, ESObject rhs) {
        return ESIntegerObject.fromValue(((ESIntegerObject)lhs).getValue() / ((ESIntegerObject)rhs).getValue());
    }

    @Override
    public ESObject mod(ESObject lhs, ESObject rhs) {
        return ESIntegerObject.fromValue(((ESIntegerObject)lhs).getValue() % ((ESIntegerObject)rhs).getValue());
    }

    @Override
    public ESObject lt(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() < ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }

    @Override
    public ESObject lte(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() <= ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }

    @Override
    public ESObject gt(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() > ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }

    @Override
    public ESObject gte(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() >= ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }

    @Override
    public ESObject eq(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() == ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }

    @Override
    public ESObject neq(ESObject lhs, ESObject rhs) {
        if(lhs.getType() == rhs.getType()) {
            return ESBooleanObject.fromValue(((ESIntegerObject)lhs).getValue() != ((ESIntegerObject)rhs).getValue());
        }
        return super.lt(lhs, rhs);
    }
}
